﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using System.Xml.Serialization;
using System.IO;

namespace DELVE_GAME
{
    public class PlayerProfileManager
    {
        const int DEFAULT_PROFILE = -1;
        const string profileDirectory = "Content/Profiles";
        const string managerFile = "profileManager.xml";

        Color[] colors;
        bool[] availableColors;
        public List<PlayerProfile> playerProfiles;
        List<bool> availableProfiles;
        //List of profile index chosen for each player index
        List<int> chosenProfiles;
        //List of color index chosen for each player index
        List<int> chosenColors;

        #region initializers

        public PlayerProfileManager()
        {
            colors = null;
            availableColors = null;
            playerProfiles = new List<PlayerProfile>();
            availableProfiles = new List<bool>();
            chosenProfiles = new List<int>();
            chosenColors = new List<int>();
        }

        public void readFromFile()
        {
            string fileLoc = profileDirectory + "/" + managerFile;
            if (File.Exists(fileLoc))
            {
                PlayerProfileManager newList = new PlayerProfileManager();
                XmlSerializer serializer = new XmlSerializer(newList.GetType());
                FileStream xmlFileStream = File.Open(fileLoc, FileMode.Open);
                newList = (PlayerProfileManager)serializer.Deserialize(xmlFileStream);
                xmlFileStream.Close();
                this.playerProfiles = newList.playerProfiles;
            }
            else writeToFile();

            initialize();



        }

        //Write this PlayerProfileManager to file
        public void writeToFile()
        {
            string fileLoc = profileDirectory + "/" + managerFile;
            if (!Directory.Exists(profileDirectory)) Directory.CreateDirectory(profileDirectory);
            XmlSerializer serializer = new XmlSerializer(this.GetType());
            StreamWriter writer = new StreamWriter(fileLoc);
            serializer.Serialize(writer, this);
            writer.Close();
        }

        private void initialize()
        {
            colors = new Color[] {Color.Yellow, Color.Purple, Color.Green, Color.Blue};
            availableColors = new bool[colors.Length];
            availableProfiles = new List<bool>(playerProfiles.Count);
        }

        public void initializeSelection(int numPlayers)
        {
            for (int i = 0; i < availableColors.Length; i++)
            {
                availableColors[i] = true;
            }
            for (int i = 0; i < playerProfiles.Capacity; i++)
            {
                availableProfiles.Add(true);
            }
            chosenProfiles = new List<int>();
            chosenColors = new List<int>();
            for (int i = 0; i < numPlayers; i++)
            {
                chosenProfiles.Add(DEFAULT_PROFILE);
                chosenColors.Add(DEFAULT_PROFILE);
            }
        }

        #endregion

        #region profile selection
        public string getProfileName(int index) 
        {
            return (index != DEFAULT_PROFILE ? playerProfiles[index].name : null);
        }

        //If unavailable, profile cannot be selected
        public bool getProfileAvailability(int index) 
        {
            return availableProfiles[index];
        }
        public int getNumProfiles() {return playerProfiles.Count;}

        /*
         * Change availableProfiles and chosenProfiles to currently selected profile for player
         */
        public void selectProfile(int player, int profile) 
        {
            if (availableProfiles[profile])
            {
                int previousProfile = chosenProfiles[player];
                if (previousProfile != DEFAULT_PROFILE)
                    availableProfiles[previousProfile] = true;
                availableProfiles[profile] = false;
                chosenProfiles[player] = profile;
            }
        }

        public Color getColor(int index)
        {
            return colors[index];
        }

        public bool getColorAvailability(int index)
        {
            return availableColors[index];
        }

        public int getNumColors() { return colors.Length; }

        /*
         * Change availableColors and chosenColors to currently selected color for player
         */
        public void selectColor(int player, int color)
        {

            if (availableColors[color])
            {
                int previousColor = chosenColors[player];
                if (previousColor != DEFAULT_PROFILE)
                    availableColors[previousColor] = true;
                availableColors[color] = false;
                chosenColors[player] = color;
            }
        }

        /*
         * New profile is added to all relevant lists and selected
         */
        public bool createProfile(string name) 
        {
            bool created = true;
            foreach (PlayerProfile profile in playerProfiles)
            {
                if (profile.name.Equals(name))
                {
                    created = false;
                    break;
                }
            }
            if(created) {
                int index = playerProfiles.Count;
                playerProfiles.Add(new PlayerProfile(name));
                availableProfiles.Add(true);
            }
            return created;
        }

        /*
         * If colors have not been chosen, set colors automatically
         */
        public void finalize()
        {
            int lastChosenColor = 0;
            for (int i = 0; i < chosenColors.Count; i++)
            {
                if (chosenColors[i] == DEFAULT_PROFILE)
                {
                    for (; !availableColors[lastChosenColor] &&
                           lastChosenColor < availableColors.Length; lastChosenColor++);
                    if (lastChosenColor < availableColors.Length)
                    {
                        availableColors[lastChosenColor] = false;
                        chosenColors[i] = lastChosenColor;
                    }
                }
            }
            writeToFile();
        }

        /*
         * Save all new stats from list of players to player profiles
         */
        public void SavePlayer(Player p, int gameType) {
            int index = chosenProfiles[p.getPlayerIndex()];
            if (index != DEFAULT_PROFILE)
            {
                PlayerProfile profile = playerProfiles[index];
                profile.games[gameType]++;
                if (p.isWinner()) profile.wins[gameType]++;
            }
            writeToFile();
        }





        #endregion

        #region in-game access
        public string getPlayerName(int playerIndex)
        {
            string name = getProfileName(chosenProfiles[playerIndex]);
            if (name == null) name = "Player " + (playerIndex + 1).ToString();
            return name;
        }
        public Color getPlayerColor(int playerIndex)
        {
            return colors[chosenColors[playerIndex]];
        }
        #endregion
    }

    [Serializable]
    public class PlayerProfile
    {
        public string name;
        public int[] games;
        public int[] wins;
        public PlayerProfile() { 
            name = null;
            games = new int[(int)GameType.NUM_TYPES];
            wins = new int[(int)GameType.NUM_TYPES];
        }
        public PlayerProfile(string newName) : this() {name = newName;}

        //Rest of stats go here
    }
}
